package com.denlaku.longan.aspect;

import com.denlaku.longan.AppException;
import com.denlaku.longan.anno.RequestLimit;
import com.denlaku.longan.core.RateLimiterManager;
import com.google.common.util.concurrent.RateLimiter;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.time.Duration;

/**
 * @author tianx
 */
@Component
@Aspect
@Slf4j
public class RequestLimitAspect {
    @Before(value = "@annotation(limit)")
    public void before(JoinPoint jp, RequestLimit limit) {
        Signature signature = jp.getSignature();
        String declaringTypeName = signature.getDeclaringTypeName();
        String name = signature.getName();
        double permitsPerSecond = limit.permitsPerSecond();
        Duration warmupPeriod = Duration.ofSeconds(limit.warmupPeriod());
        String key = declaringTypeName + "." + name;
        RateLimiter rateLimiter = RateLimiterManager.getRateLimiter(key, permitsPerSecond, warmupPeriod);
        if (!rateLimiter.tryAcquire()) {
            throw new AppException("request limit", null);
        }
    }
}
